package org.googlecode.viewt.core.tools.formbean;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.googlecode.viewt.core.tools.po.POConfigRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FormBeanGenerateCommand {
	private static Logger logger = LoggerFactory
			.getLogger(FormBeanGenerateCommand.class);
	public static final String OPT_FORMBEANCFG_FILE = "i";
	public static final String OPT_DEP_FORMBEANFILES = "dep";
	public static final String OPT_DEP_POFILES = "po";
	public static final String OPT_IMP_DEST = "imp";
	public static final String OPT_CFG_DEST = "cfg";
	public static final String OPT_PREFIX_PACKAGE = "prepack";
	public static final String OPT_COPYRIGHT = "copyright";
	public static final String OPT_AUTHOR = "author";
	private String formbeanCfgFile = null;

	private String[] dependCfgFiles = null;

	private String[] dependPOCfgFiles = null;

	private String impDestPath = null;

	private String cfgDestPath = null;

	private String prePackName = "com.leadron";

	private String copyright = null;

	private String author = null;

	private FormBeanCfgRepository formbeanRepository = new FormBeanCfgRepository();

	private POConfigRepository poRepository = new POConfigRepository();

	public void parseArgs(String[] args) throws ParseException {
		int i;

		CommandLineParser parser = new GnuParser();
		// OptionBuilder.hasArg();
		// OptionBuilder.isRequired();
		// OptionBuilder
		// .withDescription("formbean config file name by which to generate");
		// OptionBuilder.hasArg();
		// OptionBuilder.hasArgs();
		// OptionBuilder.withDescription("dependent formbean config files");
		// OptionBuilder.hasArg();
		// OptionBuilder.hasArgs();
		// OptionBuilder.withDescription("dependent PO config files");
		// OptionBuilder.hasArg();
		// OptionBuilder.isRequired();
		// OptionBuilder
		// .withDescription("path to output implementation class file");
		// OptionBuilder.hasArg();
		// OptionBuilder.isRequired();
		// OptionBuilder.withDescription("path to output config file");
		// OptionBuilder.hasArg();
		// OptionBuilder.withDescription("package prefix of generated class");
		// OptionBuilder.hasArg();
		// OptionBuilder
		// .withDescription("copyright information for generated code");
		// OptionBuilder.hasArg();
		// OptionBuilder.withDescription("author information for generated code");

		Options options = new Options().addOption(
				OptionBuilder.hasArg().isRequired().create("i")).addOption(
				OptionBuilder.hasArg().hasArgs().create("dep")).addOption(
				OptionBuilder.hasArg().hasArgs().create("po")).addOption(
				OptionBuilder.hasArg().isRequired().create("imp")).addOption(
				OptionBuilder.hasArg().isRequired().create("cfg")).addOption(
				OptionBuilder.hasArg().create("prepack")).addOption(
				OptionBuilder.hasArg().create("copyright")).addOption(
				OptionBuilder.hasArg().create("author"));

		CommandLine cmdLine = parser.parse(options, args);

		this.formbeanCfgFile = cmdLine.getOptionValue("i");
		this.dependCfgFiles = cmdLine.getOptionValues("dep");
		this.dependPOCfgFiles = cmdLine.getOptionValues("po");
		this.impDestPath = cmdLine.getOptionValue("imp");
		this.cfgDestPath = cmdLine.getOptionValue("cfg");

		if (cmdLine.hasOption("prepack"))
			this.prePackName = cmdLine.getOptionValue("prepack");
		if (cmdLine.hasOption("copyright"))
			this.copyright = cmdLine.getOptionValue("copyright");
		if (cmdLine.hasOption("author")) {
			this.author = cmdLine.getOptionValue("author");
		}

		System.out.println("FormBean config file:\t\t" + this.formbeanCfgFile);
		if (this.dependCfgFiles != null) {
			System.out.println("Dependent formbean config files:");
			for (i = 0; i < this.dependCfgFiles.length; ++i)
				System.out.println("\t" + this.dependCfgFiles[i]);
		}
		if (this.dependPOCfgFiles != null) {
			System.out.println("Dependent PO config files:");
			for (i = 0; i < this.dependPOCfgFiles.length; ++i) {
				System.out.println("\t" + this.dependPOCfgFiles[i]);
			}
		}

		System.out.println("Implement output path:\t" + this.impDestPath);
		System.out.println("Config output path:\t" + this.cfgDestPath);
		System.out.println("Package prefix:\t" + this.prePackName);
	}

	public void loadConfig() {
		logger.debug("Begin to load formbean and PO configuration...");

		this.formbeanRepository.setMainDef(this.formbeanCfgFile,
				this.prePackName);
		int len = (this.dependCfgFiles == null) ? 0
				: this.dependCfgFiles.length;
		for (int i = 0; i < len; ++i) {
			this.formbeanRepository.addFormBeanConfig(this.dependCfgFiles[i]);
		}

		len = (this.dependPOCfgFiles == null) ? 0
				: this.dependPOCfgFiles.length;
		if (len > 0) {
			this.poRepository.setMainDef(this.dependPOCfgFiles[0],
					this.prePackName);
			for (int i = 1; i < len; ++i) {
				this.poRepository.addPOConfig(this.dependPOCfgFiles[i]);
			}
		}
		logger.debug("Load formbean and PO configuration succeed");
	}

	public boolean validateConfig() throws Exception {
		logger.debug("Begin to validate configuration...");

		boolean valide = FormBeanUtil.validateConfig(this.formbeanRepository,
				this.poRepository);
		if (!(valide))
			logger.error("Validate configuration fail");
		else {
			logger.debug("Validate configuration succeed");
		}
		return valide;
	}

	public void performGen() throws Exception {
		BaseFormBeanGenerator generator = null;

		logger.debug("Begin to generate formbean implement file");
		generator = new ImpGenerator();
		generator.setPORepository(this.poRepository);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.formbeanRepository, this.impDestPath);
		generator.performGen();
		logger.debug("End generate formbean implement file");

		logger.debug("Begin to generate formbean constant file");
		generator = new ConstantGenerator();
		generator.setPORepository(this.poRepository);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.formbeanRepository, this.impDestPath);
		generator.performGen();
		logger.debug("End generate formbean constant file");

		logger.debug("Begin to generate formbean-PO mapping config");
		generator = new POMappingCfgGenerator();
		generator.setPORepository(this.poRepository);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.formbeanRepository, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate formbean-PO mapping config");

		logger.debug("Begin to generate formbean-query mapping config");
		generator = new QueryMappingCfgGenerator();
		generator.setPORepository(this.poRepository);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.formbeanRepository, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate formbean-query mapping config");
	}

	public static void main(String[] args) {
		System.out
				.println("FormBean generator, Copyright (c) 2006-2008 Leadron Information Technoloy co.,Ltd.");
		try {
			FormBeanGenerateCommand command = new FormBeanGenerateCommand();
			command.parseArgs(args);
			command.loadConfig();
			if (!(command.validateConfig())) {
				System.out.println("Validate config fail");
				System.exit(-1);
			}
			command.performGen();
		} catch (ParseException parseEx) {
			System.out.println("Invalid command line argument, check the doc");
			System.out.println(parseEx.getMessage());
			System.exit(-1);
		} catch (Exception ex) {
			System.out.println("Generate formbean source file fail");
			ex.printStackTrace();
			System.exit(-1);
		}

		System.out.println("Generation done.");
	}
}